#ifndef TCPCLIENT_H
#define TCPCLIENT_H

#include <QObject>
#include <QTcpSocket>
#include <map>

#include "protocol.h"

class TCPClient : public QObject
{
    Q_OBJECT

public:
    typedef CSProtocol::IData *(TCPClient::*createCommand)();
    TCPClient(QObject *parent);
    bool connected() { return this->_socket.isOpen(); }
    QTcpSocket &getSocket() { return _socket; }
    int getIdCommand() const { return _idCommand; }
    void incIdCommand() { _idCommand++; }
    QString &getOutData() { return _outData; }
    void setOutData(const QString &data) { _outData = data; }
    void writeData(CSProtocol::Header &header, CSProtocol::IData *data);
    void setAuthenticate(bool value) { _isAuthenticated = value; }
    bool getAuthenticate() const { return _isAuthenticated; }
    std::map<int, CSProtocol::IData*> &getWaitingCmd() { return _waitForCmd; }
    CSProtocol::Header *getReadingHeader() { return _readingHeader; }
    enum eReadingMod
    {
        readingHeader,
        readingData,
    };

    CSProtocol::IData *createWelcome() { return new CSProtocol::Welcome(); }

private:
    QTcpSocket _socket;
    void initCommands();
    CSProtocol::Header *_readingHeader;
    eReadingMod _curReadingMod;
    void setReadMod(eReadingMod mod, int size);
    int _curReadSize;
    void readToCmd(CSProtocol::IData *data);
    int _idCommand;
    QString _outData;
    std::map<int, CSProtocol::IData*> _waitForCmd;
    std::map<int, createCommand> _commands;
    bool _isAuthenticated;
private slots:
    void readData();
    void socketError(QAbstractSocket::SocketError socketError);
};

#endif // TCPCLIENT_H
